package tmt.usercenter.web.controller.bean;

import com.tmt.helper.RandomCodeHelper;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * 基于HttpServletRequest对象的工作流管理器类
 */
public class WorkFlowManager {

    private static final String NEXT_STEP = "_NEXT_STEP_";

    public static List<WorkFlowNode> initialWorkFlow(List<String> nodeList){
        if (nodeList == null || nodeList.size() <=0)
            return null;

        List<WorkFlowNode> flowNodes = new ArrayList<>();
        final WorkFlowNode[] currentNode = {null};
        nodeList.forEach(x->{
            WorkFlowNode node = new WorkFlowNode(x);
            flowNodes.add(node);
            if (currentNode[0] == null) {
                currentNode[0] = node;
                return;
            }
            currentNode[0].setNext(node);
            node.setPrevious(currentNode[0]);
            currentNode[0] = node;
        });
        return flowNodes;
    }

    /**
     * 判断从起始节点开始的链表，是否依次包含列表中指定的节点。
     * @param startNode
     * @param nodeList
     * @return
     */
    public static boolean containNodes(WorkFlowNode startNode, List<String> nodeList){
        boolean isContain = true;
        for(int i=0; i< nodeList.size(); i++){
            if (startNode == null || !nodeList.get(i).equals(startNode.getEntry())){
                isContain = false;
                break;
            }
            startNode = startNode.getNext();
        }
        return isContain;
    }

    /**
     * 判断当前Request请求对象是否处于指定的流程节点处
     * @param request
     * @param node 指定的流程节点
     * @return
     */
    public static boolean isSameFlowNode(HttpServletRequest request, WorkFlowNode node){
        return isSameFlowNode(request, node.getEntry());
    }

    public static boolean isSameFlowNode(HttpServletRequest request, String node){
        String curUrl = request.getRequestURI().replaceFirst(request.getContextPath(), "");
        String entry = node.replaceFirst("redirect:", "")
                .replaceFirst("forward:", "");
        entry = entry.split("\\?")[0];
        return curUrl.equals(entry);
    }

    /**
     * 确保当前访问的Url是与设定的下一步流程Url相同。
     * 如果相同，则返回null;
     * 如果不同则返回defaultEntry;
     * @param request
     * @param defaultEntry 为null时，仅当当前请求不处于流程节点时返回非空字符串。
     * @return
     */
    public static String assure(HttpServletRequest request, String defaultEntry){
        Object obj = current(request);
        if (obj == null)
            return defaultEntry;

        WorkFlowNode nextNode =  (WorkFlowNode) obj;
        String nextUri = nextNode.getEntry().replaceFirst("redirect:", "")
                .replaceFirst("forward:", "");
        nextUri = nextUri.split("\\?")[0];
        String currentUri = request.getRequestURI().replaceFirst(request.getContextPath(), "");
        return !currentUri.equals(nextUri) ? nextNode.getEntry() : null;
    }

    public static boolean hasNext(HttpServletRequest request){
        Object obj = request.getSession().getAttribute(NEXT_STEP);
        if (obj == null)
            return false;

        WorkFlowNode currentNode =  (WorkFlowNode) obj;
        return currentNode.getNext() != null;
    }

    public static WorkFlowNode current(HttpServletRequest request){
       Object obj = request.getSession().getAttribute(NEXT_STEP);
       return obj != null ? (WorkFlowNode) obj : null;
    }

    /**
     * 获取当前流程的下一步流程。
     * 如果下一步流程为空，则返回defaultEntry；
     * @param request
     * @param defaultEntry
     * @return
     */
    public static String next(HttpServletRequest request,  String defaultEntry){
        Object obj = request.getSession().getAttribute(NEXT_STEP);
        if (obj == null)
            return defaultEntry;

        WorkFlowNode currentNode =  (WorkFlowNode) obj;
        WorkFlowNode nextNode =  currentNode.getNext();
        if (nextNode != null) {
            request.getSession().setAttribute(NEXT_STEP, nextNode);
        }
        return nextNode != null ? nextNode.getEntry() : defaultEntry;
    }

    /**
     * 在currentNode节点的后面插入一个新的流程
     * @param request
     * @param nodeList
     */
    public static boolean insertFlowNodes(HttpServletRequest request, List<String> nodeList){
        if (request == null || nodeList == null || nodeList.size() <= 0)
            return false;

        WorkFlowNode currentNode = null;
        Object obj = request.getSession().getAttribute(NEXT_STEP);
        if (obj != null)
            currentNode = (WorkFlowNode) obj;

        //初始化工作流。
        List<WorkFlowNode> flowNodes = WorkFlowManager.initialWorkFlow(nodeList);

        //如果当前请求处于第一个流程节点上，则移除第一个节点。
        if (currentNode != null && isSameFlowNode(request, flowNodes.get(0))) {
            flowNodes.remove(0);
        }

        if (currentNode != null) {
            flowNodes.get(0).setPrevious(currentNode);
            flowNodes.get(flowNodes.size() - 1).setNext(currentNode.getNext());
            if (currentNode.getNext() != null) {
                flowNodes.get(flowNodes.size() - 1).setNext(currentNode.getNext());
                currentNode.getNext().setPrevious(flowNodes.get(flowNodes.size() - 1));
            }
            currentNode.setNext(flowNodes.get(0));
        }else{
            //如果当前节点为空，则直接加载第一个流程节点。
            request.getSession().setAttribute(NEXT_STEP, flowNodes.get(0));
        }
        return true;
    }

    public static void clear(HttpServletRequest request){
        request.getSession().removeAttribute(NEXT_STEP);
    }
}
